package com.quectel.taskserver.job.patrol;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.constant.core.securitypatrol.SecurityPatrolEventReportConstants;
import com.quectel.constant.core.securitypatrol.SecurityPatrolTaskConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.securitypatrol.dto.SecurityPatrolEventReportDto;
import com.quectel.core.module.securitypatrol.dto.SecurityPatrolTaskDto;
import com.quectel.core.module.securitypatrol.dto.SecurityPatrolTaskRouteDto;
import com.quectel.core.module.securitypatrol.service.SecurityPatrolEventReportService;
import com.quectel.core.module.securitypatrol.service.SecurityPatrolTaskRouteService;
import com.quectel.core.module.securitypatrol.service.SecurityPatrolTaskService;
import com.quectel.util.common.DateUtils;
import com.quectel.util.common.JacksonUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.text.CharSequenceUtil.splitTrim;

/**
 * @author bob
 * @email bob.yu@quectel.com
 * @date 2022/6/8 15:19
 * 巡检漏检任务扫描
 * <p>
 * 搜索条件：
 * 1、查询昨天的任务
 * 2、route_count(需巡检数量)不等于exec_count(已执行的巡检点位数量） 说明任务可能是开了没完成，或者就没开始。
 * <p>
 * 操作：
 * 1、把任务更新为结束
 * 2、还要把点位未上报的项目记录插入变成漏检
 */
@Component
public class SecurityPatrolMissedDetectionTask implements SimpleJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityPatrolMissedDetectionTask.class);

    @DubboReference
    private SecurityPatrolTaskService securityPatrolTaskService;
    @DubboReference
    private SecurityPatrolTaskRouteService securityPatrolTaskRouteService;
    @DubboReference
    private SecurityPatrolEventReportService securityPatrolEventReportService;

    @Override
    public void execute(ShardingContext shardingContext) {
        securityPatrolMissedDetectionTask();
    }

    public void securityPatrolMissedDetectionTask() {
        DateTime yesterday = DateUtil.yesterday();
        String yesterDayStr = new SimpleDateFormat(DateUtils.FormatType.SIMPLE.getType())
                .format(yesterday);
        LOGGER.info("安保巡更扫描漏检任务开始执行...扫描时间为{} 的巡检任务", yesterDayStr);

        List<SecurityPatrolTaskDto> result = new ArrayList<>();
        // 查询昨天的
        // 未执行或者执行中  的任务
        int pageNo = 1;
        while (true) {
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("startTime", yesterDayStr);
            queryMap.put("endTime", yesterDayStr);
            String statusFlag = "0,1";
            queryMap.put(SystemConstants.STATUSES, splitTrim(statusFlag, ","));
            queryMap.put("offset", (pageNo - 1) * 2000);
            queryMap.put("limit", 2000);
            List<SecurityPatrolTaskDto> list = securityPatrolTaskService.queryList(queryMap);
            if (list.size() <= 0) {
                break;
            }
            result.addAll(list);
            pageNo++;
        }

        LOGGER.info("要执行漏检的巡更任务的条数{}", result.size());

        // 过滤router_count 不等于 exec_count 的记录
        List<SecurityPatrolTaskDto> filterTaskList =
                result.stream().filter((o) -> !o.getExecCount().equals(o.getRouteCount())).collect(Collectors.toList());
        // 满足总数和已执行不相等
        if (filterTaskList.size() > 0) {

            for (SecurityPatrolTaskDto taskDto : filterTaskList) {
                try {
                    // 先要把点位未上报的项目记录插入变成漏检
                    // 去查点位表 taskId + status=-1  说明该任务的点位未执行过。
                    // 把状态改为漏检 status=3
                    Map<String, Object> queryParams = new HashMap<>();
                    queryParams.put(LambdaUtil.getFieldName(SecurityPatrolTaskRouteDto::getTaskId), taskDto.getId());
                    queryParams.put(LambdaUtil.getFieldName(SecurityPatrolTaskRouteDto::getStatus), SecurityPatrolEventReportConstants.ReportStatusEnum.NOT_CHANGED.getStatus());
                    List<SecurityPatrolTaskRouteDto> securityPatrolTaskRouteDtos = securityPatrolTaskRouteService.queryList(queryParams);
                    if (securityPatrolTaskRouteDtos.size() > 0) {
                        for (int i = 0; i < securityPatrolTaskRouteDtos.size(); i++) {
                            SecurityPatrolTaskRouteDto securityPatrolTaskRouteDto = securityPatrolTaskRouteDtos.get(i);

                            // 查询点位下的项目，并且把项目的status = -1 的上报记录
                            Map<String, Object> params = new HashMap<>();
                            params.put(LambdaUtil.getFieldName(SecurityPatrolEventReportDto::getTaskRouteId), securityPatrolTaskRouteDto.getId());
                            params.put(LambdaUtil.getFieldName(SecurityPatrolEventReportDto::getStatus), SecurityPatrolEventReportConstants.ReportStatusEnum.NOT_CHANGED.getStatus());
                            List<SecurityPatrolEventReportDto> reportDtoList = securityPatrolEventReportService.queryList(params);

                            // 上报记录更新为 status=3 漏检
                            if (reportDtoList.size() > 0) {
                                for (int j = 0; j < reportDtoList.size(); j++) {
                                    SecurityPatrolEventReportDto securityPatrolEventReportDto = reportDtoList.get(j);
                                    securityPatrolEventReportDto.setStatus(SecurityPatrolEventReportConstants.ReportStatusEnum.MISSED_DETECTION.getStatus());
                                    securityPatrolEventReportDto.setCompleteTime(new Date());
                                    securityPatrolEventReportService.updateById(securityPatrolEventReportDto);
                                }
                            }

                            //设置漏检
                            securityPatrolTaskRouteDto.setStatus(SecurityPatrolEventReportConstants.ReportStatusEnum.MISSED_DETECTION.getStatus());
                            securityPatrolTaskRouteDto.setCompleteTime(new Date());
                            securityPatrolTaskRouteService.updateById(securityPatrolTaskRouteDto);
                        }
                    }

                    // 任务route_exec_total_status更新
                    String routeExecTotalStatus = taskDto.getRouteExecTotalStatus();
                    List<Byte> routeExecTotalStatusList = JacksonUtils.parseArray(routeExecTotalStatus, Byte.class);
                    routeExecTotalStatusList.add(SecurityPatrolEventReportConstants.ReportStatusEnum.MISSED_DETECTION.getStatus());
                    taskDto.setRouteExecTotalStatus(JacksonUtils.toJsonString(routeExecTotalStatusList));

                    // 最后更新状态为漏检
                    taskDto.setExecStatus(SecurityPatrolTaskConstants.TasksStatusEnum.STATUS_MISSED_DETECTION.getStatus());
                    taskDto.setCompleteTime(new Date());
                    securityPatrolTaskService.updateById(taskDto);

                } catch (Exception e) {
                    continue;
                }
            }
        }
        LOGGER.info("{}安保巡更扫描漏检任务执行结束", yesterDayStr);

    }
}
